unit uLbmpNet;

interface

uses
  SysUtils, Classes, Windows, uDZSysUtils, uDZStream, uDZTrace, uDZPersistent,
  uDZThread, uDZSocket, uDZWinsock2, uDZIOCP, uDZHashTable,
  uLbmpPackage, uCxtConst, uAppConfig, uAppLog;

type
  TLbmpCallBack = procedure(Param: Pointer; LbmpResp: TResponsePackage);

procedure CityLoc(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);

procedure CoordLoc(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);

procedure GetState(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);

procedure Reg(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);
  
procedure Unreg(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);

implementation

procedure SendRequest(Connection: TDzCustomConnection; Request: TRequestPackage);
var
  Hdr: TLbmpPkgHdr;
  StackObj: array [0..19] of Byte;
  Stream: TDzMemoryStream;
begin
  Hdr.Signature := 'lbmp';
  Hdr.HdrLen := SizeOf(Hdr);
  Hdr.Format := Ord(afBinary);
  Hdr.ReqType := Ord(Request.ReqType);
  Hdr.Option := 0;
  Hdr.DataLen := 0;
  Stream := TDzMemoryStream(TDzMemoryStream.InitInstance(@StackObj));
  try
    Stream.Size := 1024;
    Stream.Seek(SizeOf(Hdr), soFromBeginning);
    Request.SaveToStream(Stream);
    Hdr.DataLen := Stream.Position - SizeOf(Hdr);
    Stream.Seek(0, soFromBeginning);
    Move(Hdr, Stream.Memory^, SizeOf(Hdr));
    Connection.Send(Stream.Memory^, Hdr.HdrLen + Hdr.DataLen);
  finally
    Stream.Clear;
  end;
end;

procedure DoRequest(ReqType: TRequestType; const Phone: AnsiString;
  Response: TResponsePackage); overload;
var
  Request: TRequestPackage;
  Hdr: TLbmpPkgHdr;
  Buf: array [0..19] of Byte;
  ms: TDzMemoryStream;
  Socket: TDzCustomClientSocket;
begin
  ms := TDzMemoryStream(TDzMemoryStream.InitInstance(@Buf));
  Socket := TDzClientSocket.Create;
  Request := RequestClasses[ReqType].Create;
  if ReqType in [rtGetState..rtCoordLoc] then
    TREQMultiPhone(Request).Phones.Add(Phone);
  try
    try
      Socket.Connect(AppConfig.LBSHost, AppConfig.LBSPort);
      SendRequest(Socket, Request);
      Socket.Read(Hdr, SizeOf(Hdr), nil, MSG_WAITALL);
      ms.Size := Hdr.DataLen;
      Socket.Read(ms.Memory^, ms.Size, nil, MSG_WAITALL);
      ms.Position := 0;
      Response.LoadFromStream(ms, TDzArchiveFormat(Hdr.Format));
    except
      on E: Exception do
      begin
        Response.ErrCode := CXT_E_UNKNOWN;
        Response.ErrMsg := E.Message;
      end;
    end;
  finally
    ms.Clear;
    Request.Free;
    Socket.Free;
  end;
end;

procedure DoRequest(ReqType: TRequestType; const Phone: AnsiString;
  Param: Pointer; Callback: TLbmpCallBack); overload;
var
  Response: TResponsePackage;
begin
  Response := ResponseClasses[ReqType].Create;
  DoRequest(ReqType, Phone, Response);
  try
    WriteLog(tsDebug, Response.AsXML);
    Callback(Param, Response);
  finally
    Response.Free;
  end;
end;

procedure CityLoc(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);
begin
  DoRequest(rtCityLoc, Phone, Param, Callback);
end;

procedure CoordLoc(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);
begin
  DoRequest(rtCoordLoc, Phone, Param, Callback);
end;

procedure GetState(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);
begin
  DoRequest(rtGetState, Phone, Param, Callback);
end;

procedure Reg(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);
begin
  DoRequest(rtReg, Phone, Param, Callback);
end;

procedure Unreg(const Phone: AnsiString; Param: Pointer; Callback: TLbmpCallBack);
begin
  DoRequest(rtUnReg, Phone, Param, Callback);
end;

end.
